<!DOCTYPE html>
<html lang="zh-Hans">
<meta name="theme-color" content="#FFFFFF">


<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
  <meta name="theme-color" content="#202020"/>
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  <link rel="shortcut icon" href="/images/favicon.ico" type="image/x-icon" />
  <link rel="icon" sizes="any" mask href="/images/favicon.ico" /> 
  
  

  <!-- viewjs support -->
  
    <!-- for theme: default is false -->
    <!-- for page: default is true -->
    <link  href="./css/viewer.min.css" rel="stylesheet" >
    <script src="./js/viewer.min.js" type="text/javascript" charset="utf-8"></script>
  
  
  
    <meta name="keywords" content="" />
  

  
    <meta name="description" content="分享 Java 技术，做有趣的程序员" />
  
  
  <link rel="icon" type="image/x-icon" href="/logo.png">
  <title>archives [ H E R O ]</title>
  
    <!-- stylesheets list from config.yml -->
    
      <link rel="stylesheet" href="//cdn.bootcss.com/pure/1.0.0/pure-min.css">
    
      <link rel="stylesheet" href="/css/xoxo.css">
    
  
<meta name="generator" content="Hexo 5.4.0"></head>


<body>
  <div class="nav-container">
    <nav id="menu" class="home-menu pure-menu pure-menu-horizontal">
  <a class="pure-menu-heading" href="/">
    <!-- <img class="avatar" src="/images/logo.png"> -->
    <span class="title">H E R O</span>
  </a>

  <ul class="pure-menu-list clearfix">
      
          
            <li class="pure-menu-item"><a href="/" class="pure-menu-link">首页</a></li>
          
      
          
            <li class="pure-menu-item actived"><a href="/archives/" class="pure-menu-link">归档</a></li>
          
      
          
            <li class="pure-menu-item"><a href="/tags/" class="pure-menu-link">标签</a></li>
          
      
          
            <li class="pure-menu-item"><a href="/about/" class="pure-menu-link">关于</a></li>
          
      
          
            <li class="pure-menu-item"><a href="/atom.xml" class="pure-menu-link">订阅</a></li>
          
      
  </ul>
   
</nav>
  </div>

  <div class="container" id="content-outer">
    <div class="inner" id="content-inner">
      

  
  
    
    
    <section class="post page archives">
      <h3 class="archive-year-wrap">
        <a href="/archives/2021" class="archive-year">
          2021
        </a>
      </h3>
      <div class="archives">
  
  <div class="archive" >
  <a class="post-go" href="/about-git-dff.html">
    <div>
      <span class="date">
        11-04
      </span>
      <span class="slash">/</span>
      到底什么是 Git 三方对比
    </div>

    <!--<div class="excerpt">-->
      <!--<p>问题： 为什么我在 gitlab 上提交的MR，代码diff不是两个分支的区别？</p>
<p>带有场景的举例子：</p>
<p>小A 在linke上建立的新的迭代，同时生成了代码分支 <code>dev</code>，然后 A、B两个同学都在这个迭代进行开发。小 A 基于 <code>dev</code> 分支创建了 <code>dev_A</code> 分支，小B基于dev分支创建了<code>dev_B</code> 分支。后来小A将他的变更合并到了 dev 分支，小B在开发过程中由于和master分支有冲突，所以他在本地解决冲突合并了一下 master 分支，然后又合并了一下 dev 分支，然后推送到 antcode 进行 MR，发现MR中代入了 master 的代码，和小A已经提交的代码？why？<br>-->
    <!--</div>-->
  </a>

</div>

  
  
  <div class="archive" >
  <a class="post-go" href="/OpenClash-AdguardHome-work-toghter.html">
    <div>
      <span class="date">
        07-26
      </span>
      <span class="slash">/</span>
      OpenClash 搭配 Adguard Home 使用
    </div>

    <!--<div class="excerpt">-->
      <!--<p>openwrt 中 openclash 和 adguard home 搭配使用的配置教程。</p>-->
    <!--</div>-->
  </a>

</div>

  
  
    
      </div></section>
    
    
    <section class="post page archives">
      <h3 class="archive-year-wrap">
        <a href="/archives/2019" class="archive-year">
          2019
        </a>
      </h3>
      <div class="archives">
  
  <div class="archive" >
  <a class="post-go" href="/how-get-antfin-offer.html">
    <div>
      <span class="date">
        08-24
      </span>
      <span class="slash">/</span>
      [面经] 如何拿下阿里/蚂蚁 offer
    </div>

    <!--<div class="excerpt">-->
      <!--<p>总结一下我的阿里面试，做一个记录吧。分享给需要的人。</p>-->
    <!--</div>-->
  </a>

</div>

  
  
  <div class="archive" >
  <a class="post-go" href="/solve-dp-problems.html">
    <div>
      <span class="date">
        07-29
      </span>
      <span class="slash">/</span>
      如何解决动态规划问题
    </div>

    <!--<div class="excerpt">-->
      <!--<p>曾经的我以为动态规划很神秘，很难理解。后来随着刷的动态规划相关的题越来越多，对于动态规划也就驾轻就熟了。我一开始来认识动态规划是通过概念来理解的，这对于我来说总是显得晦涩。我不是一个善于死记理论的人，反而是通过多刷题，回头再去看动态规划的使用情况则是有一种恍然大悟感。这样的获得想必也不会轻易忘记。刷题并不能让人变得聪明，但确实能够锻炼一个人的思维。</p>-->
    <!--</div>-->
  </a>

</div>

  
  
  <div class="archive" >
  <a class="post-go" href="/lock-of-synchronized.html">
    <div>
      <span class="date">
        07-19
      </span>
      <span class="slash">/</span>
      Java 中的偏向锁、轻量级锁和重量级锁
    </div>

    <!--<div class="excerpt">-->
      <!--<p>今天我们来聊聊 Synchronized 里面的各种锁：偏向锁、轻量级锁、重量级锁，以及三个锁之间是如何进行锁膨胀的。</p>-->
    <!--</div>-->
  </a>

</div>

  
  
  <div class="archive" >
  <a class="post-go" href="/2PC-and-3PC.html">
    <div>
      <span class="date">
        07-12
      </span>
      <span class="slash">/</span>
      分布式一致性协议学习笔记：2PC 和 3PC
    </div>

    <!--<div class="excerpt">-->
      <!--<p>了解分布式一致性的一些概念和理论，介绍简单常用的分布式一致性协议。主要介绍二阶段提交和三阶段提交的基本流程，并相互比较。</p>-->
    <!--</div>-->
  </a>

</div>

  
  
  <div class="archive" >
  <a class="post-go" href="/Monty-Hall-problem.html">
    <div>
      <span class="date">
        06-19
      </span>
      <span class="slash">/</span>
      三门问题
    </div>

    <!--<div class="excerpt">-->
      <!--<p>前几天有一个关注很久的公众号推送了一篇讲 “三门问题” 的文章。这不是我第一看到这个问题的分析，我一直觉得这个是个伪命题，后面两个门打开后面有大奖的概率都应该是<code>1/2</code>才对呀。直到我去看了一些分析，写了这篇文章。</p>-->
    <!--</div>-->
  </a>

</div>

  
  
  <div class="archive" >
  <a class="post-go" href="/ConcurrentModificationException.html">
    <div>
      <span class="date">
        06-03
      </span>
      <span class="slash">/</span>
      聊聊 ConcurrentModificationException
    </div>

    <!--<div class="excerpt">-->
      <!--<p>今天有朋友突然在群里抛出一句，”java中使用foreach遍历时，为啥不让删除元素呢？设计ConcurrentModificationException的意义是什么目的呢？如果单线程操作，还需要吗？” 。今天我们就来聊一聊这件事。</p>-->
    <!--</div>-->
  </a>

</div>

  
  
  <div class="archive" >
  <a class="post-go" href="/create-right-singleton.html">
    <div>
      <span class="date">
        05-30
      </span>
      <span class="slash">/</span>
      如何构建一个正确的单例
    </div>

    <!--<div class="excerpt">-->
      <!--<p>单例模式是设计模式里面最常见的，也是在面试过程中面试官最容易考到的，通过单例模式还可以引申到其他的一些并发问题。今天我们来聊聊如何正确的构建一个单例。</p>-->
    <!--</div>-->
  </a>

</div>

  
  
  <div class="archive" >
  <a class="post-go" href="/record-of-deadlock-analytics.html">
    <div>
      <span class="date">
        05-17
      </span>
      <span class="slash">/</span>
      线上死锁分析解决纪实
    </div>

    <!--<div class="excerpt">-->
      <!--<p>服务发生死锁，死锁检测时间较长，31s后死锁检测出来事务才得以回滚，期间不断有相同请求进来，造成死锁越来越复杂，并且服务端线程池中的所有线程都在等待锁，最后造成服务端线程池无空闲线程，拒绝服务。</p>
<p><strong>注意：单条 SQL 也是一个事务，也会和其他事务发生死锁。</strong></p>-->
    <!--</div>-->
  </a>

</div>

  
  
  <div class="archive" >
  <a class="post-go" href="/best-practices-of-aria2.html">
    <div>
      <span class="date">
        04-09
      </span>
      <span class="slash">/</span>
      Aria2 GUI最佳实践
    </div>

    <!--<div class="excerpt">-->
      <!--<p>目前用的爽的下载工具，通过搭配  Chrome 和 自己写的一些脚本达到不输迅雷的用户体验。</p>
<blockquote>
<p>本文在 MacOS 下可以通过所有步骤，其他平台需要自行修改相关步骤</p>
</blockquote>-->
    <!--</div>-->
  </a>

</div>

  
  
  <div class="archive" >
  <a class="post-go" href="/preparation-and-init-of-classloader.html">
    <div>
      <span class="date">
        03-25
      </span>
      <span class="slash">/</span>
      Java类加载器的准备和初始化
    </div>

    <!--<div class="excerpt">-->
      <!--<p>好久没有更新博客了，昨天在浏览微信公众号的时候看到了一道面试题，给出一个包含 main 方法的类，一些输出语句，让读者判断这些语句的输出顺序，其实也就是考察读者的对于 Java 类的初始化的顺序，看到这道题目的时候，我也就按照自己的理解得出了一个顺序，可是和答案却大相径庭，原因就在于对于 Java 类加载器在加载类时候的两个阶段：<strong>准备 </strong>和 <strong>初始化</strong> 没有足够的理解。今天我们在本文中就来聊聊类加载的这两个阶段</p>-->
    <!--</div>-->
  </a>

</div>

  
  
  <div class="archive" >
  <a class="post-go" href="/transactional-of-spring.html">
    <div>
      <span class="date">
        02-28
      </span>
      <span class="slash">/</span>
      Spring 中 Transactional 注解原理
    </div>

    <!--<div class="excerpt">-->
      <!--<p>利用 Spring 框架可以很容易的使用注解的方式来使用事务，为我们的开发带来了巨大的便利，这种便利的实现是通过 Spring 本身的一系列机制来实现的，主要包含动态代理和 Spring Bean 的加载过程。本文将深入源码，揭开层层面纱…</p>-->
    <!--</div>-->
  </a>

</div>

  
  
  <div class="archive" >
  <a class="post-go" href="/how-to-use-java-se-create-simple-httpserver.html">
    <div>
      <span class="date">
        01-24
      </span>
      <span class="slash">/</span>
      利用 JavaSE 创建简单 HTTP Server
    </div>

    <!--<div class="excerpt">-->
      <!--<p>在工作中经常会遇到简单实用 HTTP server 的场景，可是又不需要 Spring MVC 或者 web容器那样重的东西。这种情况下 JavaSE 就可以满足我们的要求了。<br>-->
    <!--</div>-->
  </a>

</div>

  
  
    
      </div></section>
    
    
    <section class="post page archives">
      <h3 class="archive-year-wrap">
        <a href="/archives/2018" class="archive-year">
          2018
        </a>
      </h3>
      <div class="archives">
  
  <div class="archive" >
  <a class="post-go" href="/idempotence-design.html">
    <div>
      <span class="date">
        12-18
      </span>
      <span class="slash">/</span>
      幂等设计
    </div>

    <!--<div class="excerpt">-->
      <!--<p>我们实际系统中有很多操作，是不管做多少次，都应该产生一样的效果或返回一样的结果。 例如</p>
<ol>
<li>前端重复提交选中的数据，应该后台只产生对应这个数据的一个反应结果；</li>
<li>我们发起一笔付款请求，应该只扣用户账户一次钱，当遇到网络重发或系统bug重发，也应该只扣一次钱；</li>
<li>发送消息，也应该只发一次</li>
<li>创建业务订单，一次业务请求只能创建一个，创建多个就会出大问题等等很多重要的情况都需要幂等的特性来支持。-->
    <!--</div>-->
  </a>

</div>

  
  
  <div class="archive" >
  <a class="post-go" href="/lock-of-mysql.html">
    <div>
      <span class="date">
        09-20
      </span>
      <span class="slash">/</span>
      MySQL 中的锁
    </div>

    <!--<div class="excerpt">-->
      <!--<p>什么是事务？什么是隔离级别？<br>数据库中使用了多少种锁？这些锁之间有什么关系？<br>数据库如何在并发度和各种并发问题中平衡？<br>-->
    <!--</div>-->
  </a>

</div>

  
  
  <div class="archive" >
  <a class="post-go" href="/meaning-of-retained-size.html">
    <div>
      <span class="date">
        08-08
      </span>
      <span class="slash">/</span>
      理解VisualVM中的保留大小(Retained Size)
    </div>

    <!--<div class="excerpt">-->
      <!--<p>是否在各种内存分析工具中看到过保留大小的概念呐，保留大小到底代表着什么？<br>保留大小代表着实例本事和引用的对象的总大小吗？</p>-->
    <!--</div>-->
  </a>

</div>

  
  
  <div class="archive" >
  <a class="post-go" href="/curses-programming-with-python.html">
    <div>
      <span class="date">
        04-19
      </span>
      <span class="slash">/</span>
      【译】Python Curses 编程
    </div>

    <!--<div class="excerpt">-->
      <!--<p>本文介绍如何使用 <a target="_blank" rel="noopener" href="https://docs.python.org/3.6/library/curses.html#module-curses">curses</a> 扩展去控制命令行模式的显示。</p>
<blockquote>
<p>原文链接：<a target="_blank" rel="noopener" href="https://docs.python.org/3.6/howto/curses.html">https://docs.python.org/3.6/howto/curses.html</a><br>原文作者: A.M. Kuchling, Eric S. Raymond<br>版本：Release-2.04</p>
</blockquote>-->
    <!--</div>-->
  </a>

</div>

  
  
  <div class="archive" >
  <a class="post-go" href="/tools-of-jvm.html">
    <div>
      <span class="date">
        01-30
      </span>
      <span class="slash">/</span>
      JVM-探究（四）：虚拟机监控和分析工具
    </div>

    <!--<div class="excerpt">-->
      <!--<p>文章用来介绍常用的虚拟机内存监控和虚拟机相关的故障排除工具。 包括<code>JDK</code>自带的命令行工具、和一些可视化工具，如<code>jvisualvm</code>。-->
    <!--</div>-->
  </a>

</div>

  
  
  <div class="archive" >
  <a class="post-go" href="/theme-and-plugin-of-atom.html">
    <div>
      <span class="date">
        01-23
      </span>
      <span class="slash">/</span>
      Atom插件和主题推荐
    </div>

    <!--<div class="excerpt">-->
      <!--<p>介绍本人使用<code>Atom</code>编辑器使用的插件和主题配置，推荐给大家使用，同时也给自己做个备份。-->
    <!--</div>-->
  </a>

</div>

  
  
  <div class="archive" >
  <a class="post-go" href="/gc-algorithms-and-garbage-collector.html">
    <div>
      <span class="date">
        01-03
      </span>
      <span class="slash">/</span>
      JVM 探究（三）：垃圾回收算法和垃圾回收器
    </div>

    <!--<div class="excerpt">-->
      <!--<p>通过介绍当前的垃圾回收器和垃圾回收算法的对比和不同的优势，来帮助读者选择适合自己的垃圾回收器。主要涉及对象存活的判断、三种垃圾回收算法以及新生代和老年代的几种传统的收集器，最后会介绍一下比较火热的<code>Garbage First(G1)收集器</code>。<br>-->
    <!--</div>-->
  </a>

</div>

  
  
    
      </div></section>
    
    
    <section class="post page archives">
      <h3 class="archive-year-wrap">
        <a href="/archives/2017" class="archive-year">
          2017
        </a>
      </h3>
      <div class="archives">
  
  <div class="archive" >
  <a class="post-go" href="/experiment-on-jvm.html">
    <div>
      <span class="date">
        11-30
      </span>
      <span class="slash">/</span>
      JVM-探究（二）：JVM实验和 GC 日志解读
    </div>

    <!--<div class="excerpt">-->
      <!--<p>本文用于记录在学习 JVM 过程中的实验，在完成《深入理解Java虚拟机》第二版第三章中的实验的基础上，同时保证在<code>JDK1.8</code>上实验的可重复性，并且针对不同的垃圾收集器做实验扩充。在对不能在<code>JDK8</code>上重现的实验代码做了修正，在实验结果中分析了JVM的部分特性, 介绍了GC日志的解读等。<br>-->
    <!--</div>-->
  </a>

</div>

  
  
  <div class="archive" >
  <a class="post-go" href="/things-about-java-gzipstream.html">
    <div>
      <span class="date">
        11-16
      </span>
      <span class="slash">/</span>
      Java压缩流GZIPStream导致的内存泄露
    </div>

    <!--<div class="excerpt">-->
      <!--<p>我们来聊聊<code>GZIPOutputStream</code> 和 <code>GZIPInputStream</code>, 如果不关闭流会引起的内存泄露问题，以及<code>GZIPStream</code>申请和释放堆外内存的流程， Let’s do it!<br>-->
    <!--</div>-->
  </a>

</div>

  
  
  <div class="archive" >
  <a class="post-go" href="/jmm-of-jvm.html">
    <div>
      <span class="date">
        11-12
      </span>
      <span class="slash">/</span>
      JVM 探究（一）：JVM内存模型概念模型
    </div>

    <!--<div class="excerpt">-->
      <!--<p>作为一个 Java 程序员，不了解 Java 内存模型就不能写出能够充分利用内存的代码。本文通过对 Java 内存模型的介绍，让读者能够了解 Java 的内存的分配情况，适合 Java 初学者或者对 JMM 不熟悉的同学。后面的博客会针对每个部分做更加深入的解释。<br>-->
    <!--</div>-->
  </a>

</div>

  
  
  <div class="archive" >
  <a class="post-go" href="/be-yourself.html">
    <div>
      <span class="date">
        11-10
      </span>
      <span class="slash">/</span>
      愿你做你自己
    </div>

    <!--<div class="excerpt">-->
      <!---->
    <!--</div>-->
  </a>

</div>


  </div></section>

    </div>

    

  </div>
  <footer class="footer text-center">
    <div id="bottom-inner">
        <a class="bottom-item-hide" href="https://jacobchang.cn/" target="_blank">主站</a>
        <!-- <a class="bottom-item-hide">·</a> -->
        <!-- <a class="bottom-item-hide" href="" target="_blank">备份站点</a> -->
        <a class="bottom-item-hide">·</a>
        <a class="bottom-item-hide" href="https://github.com/coderbean" target="_blank">GitHub</a>
        <a class="bottom-item-hide">·</a>
        <a class="bottom-item" href="https://hexo.io" target="_blank">Powered by hexo</a>
        <a class="bottom-item">·</a>
        <a class="bottom-item" href="https://github.com/coderbean/hexo-theme-xoxo" target="_blank">Theme xoxo</a>
    </div>
    <div id="bottom-inner">
        <a class="bottom-item-hide" target="_blank" rel="noopener" href="https://beian.miit.gov.cn">备案号：浙ICP备2021033778号-1</a> 
        <a class="bottom-item-hide">·</a>
        <a id="copyright" class="bottom-item"></a>
    </div>
</footer>

<script language="javascript" type="text/javascript">
    var df = new Date();
    var year = df.getFullYear();
    document.getElementById("copyright").innerHTML = "Copyright © 2017 – " + year + " 黄小豆";
</script>
  

<script>
  (function(window, document, undefined) {

    var timer = null;

    function returnTop() {
      cancelAnimationFrame(timer);
      timer = requestAnimationFrame(function fn() {
        var oTop = document.body.scrollTop || document.documentElement.scrollTop;
        if (oTop > 0) {
          document.body.scrollTop = document.documentElement.scrollTop = oTop - 50;
          timer = requestAnimationFrame(fn);
        } else {
          cancelAnimationFrame(timer);
        }
      });
    }

    var hearts = [];
    window.requestAnimationFrame = (function() {
      return window.requestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.oRequestAnimationFrame ||
        window.msRequestAnimationFrame ||
        function(callback) {
          setTimeout(callback, 1000 / 60);
        }
    })();
    init();

    function init() {
      css(".heart{z-index:9999;width: 10px;height: 10px;position: fixed;background: #f00;transform: rotate(45deg);-webkit-transform: rotate(45deg);-moz-transform: rotate(45deg);}.heart:after,.heart:before{content: '';width: inherit;height: inherit;background: inherit;border-radius: 50%;-webkit-border-radius: 50%;-moz-border-radius: 50%;position: absolute;}.heart:after{top: -5px;}.heart:before{left: -5px;}");
      attachEvent();
      gameloop();
      addMenuEvent();
    }

    function gameloop() {
      for (var i = 0; i < hearts.length; i++) {
        if (hearts[i].alpha <= 0) {
          document.body.removeChild(hearts[i].el);
          hearts.splice(i, 1);
          continue;
        }
        hearts[i].y--;
        hearts[i].scale += 0.004;
        hearts[i].alpha -= 0.013;
        hearts[i].el.style.cssText = "left:" + hearts[i].x + "px;top:" + hearts[i].y + "px;opacity:" + hearts[i].alpha + ";transform:scale(" + hearts[i].scale + "," + hearts[i].scale + ") rotate(45deg);background:" + hearts[i].color;
      }
      requestAnimationFrame(gameloop);
    }

    /**
     * 设置点击事件
     * 
     * - 回到顶部
     * - 出现爱心
     */
    function attachEvent() {
      var old = typeof window.onclick === "function" && window.onclick;
      var logo = document.getElementById("menu");
      if (logo) {
        logo.onclick = function(event) {
          // returnTop();
          old && old();
          createHeart(event);
        }
      }
      
    }

    function createHeart(event) {
      var d = document.createElement("div");
      d.className = "heart";
      hearts.push({
        el: d,
        x: event.clientX - 5,
        y: event.clientY - 5,
        scale: 1,
        alpha: 1,
        color: randomColor()
      });
      document.body.appendChild(d);
    }

    function css(css) {
      var style = document.createElement("style");
      style.type = "text/css";
      try {
        style.appendChild(document.createTextNode(css));
      } catch (ex) {
        style.styleSheet.cssText = css;
      }
      document.getElementsByTagName('head')[0].appendChild(style);
    }

    function randomColor() {
      // return "rgb(" + (~~(Math.random() * 255)) + "," + (~~(Math.random() * 255)) + "," + (~~(Math.random() * 255)) + ")";
      return "#F44336";
    }

    function addMenuEvent() {
      var menu = document.getElementById('menu-main-post');
      if (menu) {
        var toc = document.getElementById('toc');
        if (toc) {
          menu.onclick = function() {
            if (toc) {
              if (toc.style.display == 'block') {
                toc.style.display = 'none';
              } else {
                toc.style.display = 'block';
              }
            }
          };
        } else {
          menu.style.display = 'none';
        }
      }
    }

  })(window, document);
</script>

  


  <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
                  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
              m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
      ga('create', 'UA-155080039-1', 'auto');
      ga('send', 'pageview');
  </script>


  
<link rel='stylesheet' href='https://s3-us-west-2.amazonaws.com/s.cdpn.io/1462889/unicons.css'>

<div class="progress-wrap">
    <svg class="progress-circle svg-content" width="100%" height="100%" viewBox="-1 -1 102 102">
        <path d="M50,1 a49,49 0 0,1 0,98 a49,49 0 0,1 0,-98" />
    </svg>
</div>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.0/jquery.min.js'></script>
<script>

    (function ($) {
        "use strict";
        $(document).ready(function () {
            "use strict";

            //Scroll back to top

            var progressPath = document.querySelector('.progress-wrap path');
            var pathLength = progressPath.getTotalLength();
            progressPath.style.transition = progressPath.style.WebkitTransition = 'none';
            progressPath.style.strokeDasharray = pathLength + ' ' + pathLength;
            progressPath.style.strokeDashoffset = pathLength;
            progressPath.getBoundingClientRect();
            progressPath.style.transition = progressPath.style.WebkitTransition = 'stroke-dashoffset 10ms linear';
            var updateProgress = function () {
                var scroll = $(window).scrollTop();
                var height = $(document).height() - $(window).height();
                var progress = pathLength - (scroll * pathLength / height);
                progressPath.style.strokeDashoffset = progress;
            }
            updateProgress();
            $(window).scroll(updateProgress);
            var offset = 50;
            var duration = 550;
            jQuery(window).on('scroll', function () {
                if (jQuery(this).scrollTop() > offset) {
                    jQuery('.progress-wrap').addClass('active-progress');
                } else {
                    jQuery('.progress-wrap').removeClass('active-progress');
                }
            });
            jQuery('.progress-wrap').on('click', function (event) {
                event.preventDefault();
                jQuery('html, body').animate({ scrollTop: 0 }, duration);
                return false;
            })


        });

    })(jQuery);
</script>

  
<!-- for theme: default is false -->
<!-- for page: default is true -->
<!-- 图片查看器实例配置 -->
<script type="text/javascript">
    //默认设置， 可以根据个人需求和喜好进行配置
    //详细参考官方说明
    Viewer.setDefaults({
        //设置初始缩放 default: 1
        zoomRatio: [0.5],
        // 过渡动画
        transition:true,
        // 显示工具条
        toolbar: false,
    });
    //获得content中所有的图片， 不同主题可能有所不同
    //为了和其他的图片区别开来 所以在markdown中插入图片的时候使用独特的记号
    //为了一次性得到所有的图片我这里采用的是class = 'article-image'
    var article = document.querySelector('.post-content');
    if(article!=null) {
        var imageList = article.getElementsByTagName('img');
        //将获取到的HTMLCollections转化成Array
        var imageArray = new Array();
        Array.prototype.forEach.call(imageList, element => {
            imageArray.push(element);
        });
        //设置每个图片成为图片组
        Array.prototype.forEach.call(imageList, element => {
            var viewer1 = new Viewer(element);
            viewer1.images = imageArray;
            viewer1.length = imageArray.length;
        });
    }

    
</script>

  
  <! -- mathjax config similar to math.stackexchange -->

<script type="text/x-mathjax-config">
MathJax.Hub.Config({
tex2jax: {
          inlineMath: [ ['$','$'], ["\\(","\\)"]  ],
                processEscapes: true
                    
}
  
        });
</script>

<script type="text/x-mathjax-config">
MathJax.Hub.Config({
tex2jax: {
            skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
                  
}
    
        });
</script>

<script type="text/x-mathjax-config">
MathJax.Hub.Queue(function() {
            var all = MathJax.Hub.getAllJax(), i;
            for(i=0; i < all.length; i += 1) {
                            all[i].SourceElement().parentNode.className += ' has-jax';
                                    
            }
                
        });
</script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_CHTML"></script>

</script>

  
</body>

</html>